package com.shoulder.mybatis.handler;

import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.extension.plugins.handler.MultiDataPermissionHandler;
import com.shoulder.core.annotation.ScopeAuth;
import com.shoulder.core.holder.SpringContextHolder;
import com.shoulder.core.properties.MyBatisProperties;
import com.shoulder.core.utils.TokenUtils;
import com.shoulder.mybatis.utils.ScopeUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.schema.Table;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;

/**
 * Copyright (c) 2024-2050 heguangchuan <596767880@qq.com>
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * <a href="http://www.apache.org/licenses/LICENSE-2.0">...</a>
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * <p>
 * 哎 太难了 没想到只是写着玩玩  却耐着性子一直写下来了
 *
 * @author 596767880@qq.com
 * @since 2024/5/8 上午9:39
 */
@Slf4j
@AllArgsConstructor
public class DataScopeHandler implements MultiDataPermissionHandler {
    private final MyBatisProperties properties;


    @Override
    public Expression getSqlSegment(Table table, Expression where, String mappedStatementId) {

        //是否开启注解权限 如果开启以注解上的权限为准,如果未开启以配置文件为准
        String className = mappedStatementId.substring(0, mappedStatementId.lastIndexOf("."));
        String beanName = StringUtils.uncapitalize(className.substring(className.lastIndexOf(".") + 1));
        Object bean = SpringContextHolder.getBean(beanName);
        String methodName = mappedStatementId.substring(mappedStatementId.lastIndexOf(".") + 1);

        ScopeAuth scopeAuth = null;
        for (Class<?> interfaces : ClassUtils.getAllInterfaces(bean)) {
            Method[] methods = interfaces.getDeclaredMethods();
            for (Method method : methods) {
                if (method.getName().equals(methodName) && method.isAnnotationPresent(ScopeAuth.class)) {
                    scopeAuth = method.getAnnotation(ScopeAuth.class);
                    break;
                }
            }
            if (scopeAuth != null) {
                break;
            }
        }

        //不需要
        if (scopeAuth != null && !scopeAuth.required()) {
            return null;
        }


        TableInfo tableInfo = TableInfoHelper.getTableInfo(table.getName());
        String sqlSelect = tableInfo.getAllSqlSelect();

        //先做租户的过滤 再自定义字段过滤
        String whereString = where == null ? "" : where.toString();
        Expression tenantExpression = null;
        //查询条件中无 tenant_id 字段
        if (ObjectUtils.isEmpty(whereString) || !whereString.toLowerCase().contains("tenant_id")) {
            // 数据表中有 tenant_id 字段
            if (sqlSelect.toLowerCase().contains("tenant_id")) {
                try {
                    tenantExpression = ScopeUtils.buildTenantExpression(table.getAlias() == null ? null : table.getAlias().getName(), TokenUtils.parseUser() == null ? "" : TokenUtils.parseUser().getTenantId());
                } catch (JSQLParserException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        String column = "";


        //未开启自定义的数据权限
        if (scopeAuth != null) {
            column = scopeAuth.column();
        } else {
            if (properties.getDataScope()) {
                column = properties.getColumn();
            }
        }
        if (StringUtils.isEmpty(column)) {
            return tenantExpression;
        }
        Expression expression;
        try {
            expression = ScopeUtils.enhanceExpression(table.getAlias() == null ? null : table.getAlias().getName(), column, TokenUtils.parseUser());
        } catch (JSQLParserException e) {
            throw new RuntimeException(e);
        }
        if (expression == null) {
            return tenantExpression;
        }

        //如果SQL中已经有了对应字段的where查询条件则不再拼装
        if (whereString.toLowerCase().contains(column)) {
            log.info("sql中已包含字段:{},不进行增强", column);
            return tenantExpression;
        }
        //如果表中没有配置的字段 也不拼装
        if (!sqlSelect.toLowerCase().contains(column)) {
            log.info("数据表:{} 中无字段:{},不进行增强", table.getName(), column);
            return tenantExpression;
        }
        return tenantExpression == null ? expression : new AndExpression(tenantExpression, expression);
    }
}
